package com.dsg.controller.bank;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSONObject;
import com.dsg.common.constants.DsgStatusConstant;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.common.util.toolbox.StringUtil;
import com.dsg.dao.account.DsgAccountCardMapper;
import com.dsg.entity.bank.DsgBankDetail;
import com.dsg.entity.bank.DsgBankRecord;
import com.dsg.entity.bank.DsgBankResult;
import com.dsg.entity.model.bank.DsgBankDetailModel;
import com.dsg.service.account.IDsgAccountTradeService;
import com.dsg.service.bank.IDsgBankDetailService;
import com.dsg.service.bank.IDsgBankRecordService;
import com.dsg.service.bank.IDsgBankResultService;
import com.dsg.util.RRException;
import com.dsg.util.verify.VerifyHolder;
import com.dsg.util.verify.impl.NotEmptyVerify;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: erp
 * @description:
 * @author: lironglai
 * @create: 2020-08-17 20:30
 */
@Slf4j
public class UploadDsgBankDetail extends AnalysisEventListener<DsgBankDetailModel> {

    private IDsgBankRecordService dsgBankRecordService;

    private IDsgBankDetailService dsgBankDetailService;

    private IDsgBankResultService dsgBankResultService;

    private IDsgAccountTradeService dsgAccountTradeService;

    private DsgAccountCardMapper dsgAccountCardMapper;

    private List<DsgBankDetail> list = new ArrayList<>();

    private List<DsgBankResult> dsgBankResultList = new ArrayList<>();

    private List<String> errorList = new ArrayList();

    private VerifyHolder verifyHolder;

    private int totalSize = 1;

    private String id;
    /**
     * 成功數量
     */
    private BigDecimal success = BigDecimal.ZERO;
    /**
     * 失敗數量
     */
    private BigDecimal fail = BigDecimal.ZERO;
    /**
     * 成功總金額
     */
    private BigDecimal successAmt = BigDecimal.ZERO;
    /**
     * 失敗總金額
     */
    private BigDecimal failAmt = BigDecimal.ZERO;
    /**
     * 每隔2条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 3000;

    public UploadDsgBankDetail(String id, IDsgBankRecordService dsgBankRecordService,
                               IDsgBankDetailService dsgBankDetailService, IDsgBankResultService dsgBankResultService,
                               DsgAccountCardMapper dsgAccountCardMapper, IDsgAccountTradeService dsgAccountTradeService) {
        this.id = id;
        this.dsgBankRecordService = dsgBankRecordService;
        this.dsgBankDetailService = dsgBankDetailService;
        this.dsgBankResultService = dsgBankResultService;
        this.dsgAccountTradeService = dsgAccountTradeService;
        this.dsgAccountCardMapper = dsgAccountCardMapper;
        //数据格式校验
        verifyHolder = new VerifyHolder(DsgBankDetailModel.class, errorList);
        verifyHolder.addVerify(new NotEmptyVerify());
    }

    /**
     * 这个每一条数据解析都会来调用  初始化 进来就要调用到的方法
     *
     * @param dsgBankDetailModel
     * @param analysisContext
     */
    @Override
    public void invoke(DsgBankDetailModel dsgBankDetailModel, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSONObject.toJSON(dsgBankDetailModel));
        totalSize++;
        try {
            verifyHolder.check(dsgBankDetailModel, totalSize);
        } catch (Exception e) {
            log.error("檢驗數據異常:", e);
            throw new RRException("檢驗數據異常", e);
        }
        DsgBankDetail dsgBankDetail = new DsgBankDetail();
        BeanUtils.copyProperties(dsgBankDetailModel, dsgBankDetail);
        if (StringUtil.isNotEmpty(dsgBankDetailModel.getResponse())) {
            switch (dsgBankDetailModel.getResponse()) {
                //成功
                case DsgStatusConstant.EXCEL_APPROVED:
                    //成功已過簽賬額
                case  DsgStatusConstant.EXCEL_DECLINED:
                    success = success.add(BigDecimal.ONE);
                    successAmt = successAmt.add(dsgBankDetail.getTranValue());
                    dsgBankDetail.setStatus(DsgBankDetail.AppStatus.success.getCode().intValue());
                    break;
                //信用咭已不能使用
                case DsgStatusConstant.EXCEL_PICKUP:
                    //信用咭已不能使用
                case DsgStatusConstant.EXCEL_INVALID_DATA:
                    fail = fail.add(BigDecimal.ONE);
                    failAmt = failAmt.add(dsgBankDetail.getTranValue());
                    dsgBankDetail.setStatus(DsgBankDetail.AppStatus.failure.getCode().intValue());
                    break;
            }
        }
        list.add(dsgBankDetail);
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param analysisContext
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (CollectionUtil.isNotEmpty(errorList)) {
            throw new RRException(errorList.toString());
        } else {
            if (CollectionUtil.isNotEmpty(list)) {
                //更新銀行往來過數檔案
                DsgBankRecord dsgBankRecord = dsgBankRecordService.getById(id);
                if (dsgBankRecord != null) {
                    dsgBankRecord.setSuccTranNumber(success.intValue());
                    dsgBankRecord.setSuccTranAmount(successAmt);
                    dsgBankRecord.setFailTranNumber(fail.intValue());
                    dsgBankRecord.setFailTranAmount(failAmt);
                    dsgBankRecordService.updateById(dsgBankRecord);
                    log.info("=========================================所有数据解析完成了");
                    dsgBankDetailService.bankCountingResults(dsgBankRecord, list);
                } else {
                    log.info(String.format("無銀行往來過數檔案數據"));
                    throw new RRException("無銀行往來過數檔案數據！");
                }
            } else {
                log.info(String.format("無銀行往來過數結果數據"));
                throw new RRException("無銀行往來過數結果數據！");
            }
        }
    }
}
